import random
import sqlite3
from datetime import datetime

import cv2
import numpy as np
from fastapi import UploadFile, File, HTTPException
from fastapi.responses import JSONResponse

from fastapi import APIRouter

from server.tools import calculate_parking_fee, recognize_plate

recognize_router = APIRouter()
import os

# 图片存储根目录（需提前创建）
IMAGE_STORAGE_DIR = "./parking_images"
os.makedirs(IMAGE_STORAGE_DIR, exist_ok=True)  # 自动创建目录


# 车辆进入停车场时的车牌识别以及停车位分配
@recognize_router.post("/entry-recognize/")
async def entry_recognize(file: UploadFile = File(...)):
    if not file.content_type.startswith('image/'):
        raise HTTPException(status_code=400, detail="File is not an image")

    try:
        # 读取图片内容
        contents = await file.read()
        img = cv2.imdecode(np.frombuffer(contents, np.uint8), cv2.IMREAD_COLOR)
        plate_number = recognize_plate(img)
        if not plate_number:
            return JSONResponse(status_code=400, content={"message": "无法识别车牌，请调整位置"})

        conn = sqlite3.connect('./license_plates.db')
        c = conn.cursor()

        # 检查车辆是否已在场
        c.execute("SELECT * FROM current_plates WHERE plate_number = ?", (plate_number,))
        if c.fetchone():
            conn.close()
            return JSONResponse(status_code=400, content={"message": "该车牌号已存在！"})
        c.execute("SELECT * FROM abnormal_plates WHERE plate_number = ?", (plate_number,))
        if c.fetchone():
            conn.close()
            return JSONResponse(status_code=400, content={"message": "该车牌号已存在！"})

        # 获取可用车位
        available_locations = get_available_locations(conn)
        if not available_locations:
            conn.close()
            return JSONResponse(status_code=400, content={"message": "当前已满，没有空车位！"})
        location = random.choice(available_locations)

        # 生成本地文件路径（使用唯一文件名避免冲突）
        file_extension = file.filename.split(".")[-1] if "." in file.filename else "jpg"
        entry_filename = f"entry_{plate_number}_{datetime.now().strftime('%Y%m%d%H%M%S')}.{file_extension}"
        entry_filepath = os.path.join(IMAGE_STORAGE_DIR, entry_filename)

        # 保存图片到本地
        with open(entry_filepath, "wb") as f:
            f.write(contents)

        # 插入数据库（存储文件路径而非二进制数据）
        enter_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        c.execute(
            "INSERT INTO current_plates (plate_number, enter_time, filename, location) VALUES (?, ?, ?, ?)",
            (plate_number, enter_time, entry_filename, location)  # 存储文件路径
        )
        # **插入 plates 表（历史记录初始值，exit_time 留空）**
        c.execute(
            "INSERT INTO plates (plate_number, enter_time, filename, location) VALUES (?, ?, ?, ?)",
            (plate_number, enter_time, entry_filename, location)
        )
        conn.commit()
        conn.close()

        return {
            "filename": file.filename,
            "detected_plate": plate_number,
            "enter_time": enter_time,
            "location": location,
            "message": "入场成功，车位已分配，图片已保存"
        }

    except Exception as e:
        if 'conn' in locals() and conn:
            conn.close()
        raise HTTPException(status_code=500, detail=f"Error: {str(e)}")


# 新增：获取可用车位函数（从 current_plates 表查询）
def get_available_locations(conn: sqlite3.Connection) -> list[int]:
    c = conn.cursor()
    c.execute("SELECT location FROM current_plates")
    a = c.fetchall()
    c.execute("SELECT location FROM abnormal_plates")
    b = c.fetchall()
    occupied = {row[0] for row in a + b}
    return [loc for loc in range(1, 101) if loc not in occupied]


# 车辆离开停车场的车牌识别
@recognize_router.post("/exit-and-recognize/")
async def exit_and_recognize(file: UploadFile = File(...)):
    if not file.content_type.startswith('image/'):
        raise HTTPException(status_code=400, detail="File is not an image")

    try:
        contents = await file.read()  # 读取离场照片二进制数据
        img = cv2.imdecode(np.frombuffer(contents, np.uint8), cv2.IMREAD_COLOR)
        plate_number = recognize_plate(img)
        if not plate_number:
            return JSONResponse(status_code=400, content={"message": "无法识别车牌，请调整位置"})

        conn = sqlite3.connect('./license_plates.db')
        c = conn.cursor()

        # 查询当前在场车辆
        c.execute(
            "SELECT id, enter_time, location, filename FROM current_plates WHERE plate_number = ?",
            (plate_number,)
        )
        current_plate = c.fetchone()
        if not current_plate:
            conn.close()
            return JSONResponse(status_code=400, content={"message": "车辆未入场或已离场"})

        # 计算停车费用和时长
        enter_time = datetime.strptime(current_plate[1], "%Y-%m-%d %H:%M:%S")
        exit_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        exit_time_dt = datetime.strptime(exit_time, "%Y-%m-%d %H:%M:%S")
        parking_seconds = (exit_time_dt - enter_time).total_seconds()
        total_fee = calculate_parking_fee(parking_seconds)

        # 生成本地文件路径（使用唯一文件名避免冲突）
        file_extension = file.filename.split(".")[-1] if "." in file.filename else "jpg"
        exit_filename = f"entry_{plate_number}_{datetime.now().strftime('%Y%m%d%H%M%S')}.{file_extension}"
        exit_filepath = os.path.join(IMAGE_STORAGE_DIR, exit_filename)

        # 保存图片到本地
        with open(exit_filepath, "wb") as f:
            f.write(contents)

            # **更新 plates 表中的历史记录**
        c.execute(
            """
            UPDATE plates
            SET exit_time = ?,
                exit_filename = ?,
                parking_seconds = ?,
                total_fee = ?
            WHERE plate_number = ?
              AND exit_time IS NULL
            """,
            (exit_time, exit_filename, parking_seconds, total_fee, plate_number,)
        )

        # 删除当前在场记录
        c.execute("DELETE FROM current_plates WHERE plate_number = ?", (plate_number,))
        conn.commit()
        conn.close()

        return {
            "detected_plate": plate_number,
            "location": current_plate[2],
            "exit_time": exit_time,
            "parking_time": str(exit_time_dt - enter_time),
            "should_pay": total_fee,
            "message": "离场成功，费用已结算"
        }

    except Exception as e:
        if 'conn' in locals() and conn:
            conn.close()
        raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
